package com.jyy.prefabricated.controller;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jyy.prefabricated.common.AjaxResult;
import com.jyy.prefabricated.dto.Pageable;
import com.jyy.prefabricated.dto.StudentExamDto;
import com.jyy.prefabricated.entity.Exam;
import com.jyy.prefabricated.entity.Student;
import com.jyy.prefabricated.entity.StudentExam;
import com.jyy.prefabricated.entity.SysUser;
import com.jyy.prefabricated.enums.ExamStatusEnum;
import com.jyy.prefabricated.enums.UserTypeEnum;
import com.jyy.prefabricated.exception.CustomException;
import com.jyy.prefabricated.service.ExamService;
import com.jyy.prefabricated.service.StudentExamService;
import com.jyy.prefabricated.utils.DateUtils;
import com.jyy.prefabricated.utils.ExcelUtil;
import com.jyy.prefabricated.utils.UserUtils;
import com.jyy.prefabricated.vo.*;
import junit.framework.Test;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 学员考试
 *
 * @version 1.0.0
 * @author: zjj
 */
@Slf4j
@RequestMapping("/api")
@RestController
public class StudentExamController {

    @Autowired
    private StudentExamService studentExamService;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private ExamService examService;

    /**
     * 参加学员考试
     *
     * @param dto
     * @return
     */
    @PostMapping("/student-exam")
    public AjaxResult insert(@Valid @RequestBody StudentExamDto dto) {
        log.info("Rest request to insert studentExam:{}", dto);
        Student student = userUtils.getCurrentStudent();
        dto.setStudentId(student.getId());
        List<StudentExam> studentExams = studentExamService.selectByStudentIdAndExamId(dto.getStudentId(), dto.getExamId());
        if (studentExams.stream().filter(e -> ExamStatusEnum.BEFORE.getValue().equals(e.getStatus())).count() > 0) {
            //系统预生成的考试信息
            StudentExam studentExam = studentExams.stream().filter(e -> ExamStatusEnum.BEFORE.getValue().equals(e.getStatus())).findAny().get();
            Exam exam = examService.selectById(studentExam.getExamId());
            long startTime = DateUtils.parseDate(exam.getExamStartTime()).getTime();
            long endTime = DateUtils.parseDate(exam.getExamEndTime()).getTime();
            long now = DateUtils.getUct8NowDate().getTime();
            if (now >= startTime && now < endTime) {
                studentExam.setCreateTime(DateUtils.getUct8NowDate());
                studentExam.setStatus(ExamStatusEnum.DOING.getValue());
                studentExamService.update(studentExam);
                return AjaxResult.success(studentExam);
            } else {
                throw new CustomException("当前考试还未开始！");
            }

        }
        if (studentExams.stream().filter(e -> !ExamStatusEnum.AFTER.getValue().equals(e.getStatus())).count() > 0) {
            return AjaxResult.success(studentExams.stream().filter(e -> !ExamStatusEnum.AFTER.getValue().equals(e.getStatus())).findAny().get());
        }
        Integer id = studentExamService.insert(dto);
        StudentExam result = studentExamService.selectById(id);
        return AjaxResult.success(result);
    }



    /**
     * 查询学员考试详情
     *
     * @param id
     * @return
     */
    @GetMapping("/student-exam/{id}")
    public AjaxResult selectById(@PathVariable Integer id) {
        log.info("Rest request to find studentExam by id:{}", id);
        StudentExam result = studentExamService.selectById(id);
        return AjaxResult.success(result);
    }

    /**
     * 查询当前学生最近的考试信息
     *
     * @return
     */
    @GetMapping("/student-exam")
    public AjaxResult selectCurrentExam() {
        log.info("Rest request to find current studentExam ");
        Student student = userUtils.getCurrentStudent();
        List<StudentExamVo> list = studentExamService.selectCurrentExamByStudentId(student.getId());
        List<StudentExamVo> result = list.stream().filter(e -> e.getExamCount() > e.getCurrentCount()).collect(Collectors.toList());
        if (result.size() > 0) {
            return AjaxResult.success(result);
        }
        return AjaxResult.error("当前学生没有待参加的考试！");
    }

    /**
     * 查询考试成绩（批阅列表）
     *
     * @param studentName            姓名
     * @param idCard                 身份证
     * @param trainingOrganizationId 培训机构id
     * @param examId                 考试id
     * @param readOverStatus         批阅状态
     * @return
     * @pparam Pageable pageable
     */
    @GetMapping("/student-exam-score")
    public AjaxResult selectExamScore(@RequestParam(required = false, defaultValue = "") String studentName, @RequestParam(required = false, defaultValue = "") String idCard, @RequestParam(required = false) Integer pointId, @RequestParam(required = false) Integer trainingOrganizationId, @RequestParam(required = false) Integer examApplyId, @RequestParam(required = false) Integer examId,@RequestParam(required = false) Integer readOverStatus, Pageable pageable) {
        log.info("Rest request to find student exam score by studentName:{},idCard:{},pointId:{},trainingOrganizationId:{},examApplyId:{}", studentName, idCard, pointId, trainingOrganizationId, examApplyId);
        SysUser user = userUtils.getCurrentUser();
        PageHelper.startPage(pageable.getPageNum(), pageable.getPageSize());
        Integer studentId = null;
        if (UserTypeEnum.ADMIN.getValue().equals(user.getUserType())) {
            //管理员查询
        } else if (UserTypeEnum.TRAININGORGANIZATION.getValue().equals(user.getUserType())) {
            trainingOrganizationId = user.getTrainingOrganization().getId();
        } else if (UserTypeEnum.STUDENT.getValue().equals(user.getUserType())) {
            studentId = user.getStudent().getId();
        }
        List<StudentExamScoreVo> list = studentExamService.selectScoreByParams(studentName, idCard, pointId, examApplyId, trainingOrganizationId, studentId, examId ,readOverStatus);
        PageInfo<StudentExamScoreVo> result = new PageInfo<>(list);
        return AjaxResult.success(result);
    }

    /**
     * 查询考试成绩(导出成绩单)
     *
     * @return
     */
    @GetMapping("/student-exam-excel")
    public void downloadScoreExcel(@RequestParam(required = false, defaultValue = "") String studentName, @RequestParam(required = false, defaultValue = "") String idCard, @RequestParam(required = false) Integer pointId, @RequestParam(required = false) Integer trainingOrganizationId, @RequestParam(required = false) Integer examApplyId,@RequestParam(required = false) Integer examId, HttpServletResponse response) {
        log.info("Rest request to download student exam score by studentName:{},idCard:{},pointId:{},trainingOrganizationId:{},examApplyId:{}", studentName, idCard, pointId, trainingOrganizationId, examApplyId);
        SysUser user = userUtils.getCurrentUser();
        Integer studentId = null;
        if (UserTypeEnum.ADMIN.getValue().equals(user.getUserType())) {
            //管理员查询
        } else if (UserTypeEnum.TRAININGORGANIZATION.getValue().equals(user.getUserType())) {
            trainingOrganizationId = user.getTrainingOrganization().getId();
        } else if (UserTypeEnum.STUDENT.getValue().equals(user.getUserType())) {
            studentId = user.getStudent().getId();
        }
        List<StudentExamScoreVo> list = studentExamService.selectScoreByParams(studentName, idCard, pointId, examApplyId, trainingOrganizationId, studentId, examId ,null);
        downloadExcel(list, response);
    }

    /**
     * 导出excel
     *
     * @param list
     * @param response
     */
    public void downloadExcel(List<StudentExamScoreVo> list, HttpServletResponse response) {
        String title = "考试成绩";
        Workbook workbook = writeDataToExcel(list);
        try {
            ExcelUtil.downloadExcel(response, workbook, title);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将数据写入excel
     *
     * @param list
     * @return
     */
    public Workbook writeDataToExcel(List<StudentExamScoreVo> list) {
        String[] titleList = {"排名", "考试名称", "考核点", "培训机构", "姓名", "身份证号", "客观题分数", "主观题分数", "总分", "答题用时", "答题结束时间"};
        InputStream is = Test.class.getClassLoader().getResourceAsStream("templates/studentExamScore.xlsx");
        //检查模板文件
        Workbook workbook = null;
        try {
            workbook = new XSSFWorkbook(is);
            if (workbook != null) {
                for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
                    //获得当前sheet工作表
                    Sheet sheet = workbook.getSheetAt(sheetNum);
                    if (sheet == null) {
                        continue;
                    }
                    //获得当前sheet的结束行
                    int lastRowNum = sheet.getLastRowNum();
                    Row firstRow = sheet.getRow(lastRowNum - 1);
                    int columnNum = 0;
                    if (firstRow != null) {
                        columnNum = firstRow.getPhysicalNumberOfCells();
                    }
                    for (int j = 0; j < columnNum; j++) {
                        Cell cell = firstRow.getCell(j); //第1行,第j列
                        String cellValue = cell.getStringCellValue();
                        System.out.println(cellValue);
                    }
                    Row row = sheet.createRow(lastRowNum + 1);
                    //创建内容
                    Cell dataCell = null;
                    Long count = 0L;
                    for (int i = 0; i < list.size(); i++) {
                        row = sheet.createRow(lastRowNum + i + 1);
                        for (int j = 0; j < titleList.length; j++) {
                            dataCell = row.createCell(j);
                            if (j == 0) {
                                if (list.get(i).getTotalScore() == null) {
                                    list.get(i).setTotalScore(0D);
                                }
                                if (i != 0 && list.get(i - 1).getTotalScore() == null) {
                                    list.get(i - 1).setTotalScore(0D);
                                }
                                if (i != 0 && list.get(i).getTotalScore().equals(list.get(i - 1).getTotalScore())) {
                                    dataFormat(dataCell, count);
                                } else {
                                    count = i + 1L;
                                    dataFormat(dataCell, count);
                                }
                            } else if (j == 1) {
                                String value = list.get(i).getExamName();
                                dataFormat(dataCell, value);
                            } else if (j == 2) {
                                String value = list.get(i).getPointName();
                                dataFormat(dataCell, value);
                            } else if (j == 3) {
                                String value = list.get(i).getTrainingOrganizationName();
                                dataFormat(dataCell, value);
                            } else if (j == 4) {
                                String value = list.get(i).getStudentName();
                                dataFormat(dataCell, value);
                            } else if (j == 5) {
                                String value = list.get(i).getIdCard();
                                dataFormat(dataCell, value);
                            } else if (j == 6) {
                                Double value = list.get(i).getScore();
                                if (value != null) {
                                    dataFormat(dataCell, value);
                                } else {
                                    dataFormat(dataCell, "缺考");
                                }
                            } else if (j == 7) {
                                Double value = list.get(i).getSubjectiveScore();
                                if (value != null) {
                                    dataFormat(dataCell, value);
                                } else {
                                    dataFormat(dataCell, "缺考");
                                }
                            } else if (j == 8) {
                                Double value = list.get(i).getTotalScore();
                                if (value != null) {
                                    dataFormat(dataCell, value);
                                } else {
                                    dataFormat(dataCell, "缺考");
                                }
                            } else if (j == 9) {
                                String value = "";
                                Integer seconds = list.get(i).getUseTime();
                                if (seconds != null) {
                                    int min = seconds / 60;
                                    int second = seconds % 60;
                                    value = min + "分钟" + second + "秒";
                                } else {
                                    value = "缺考";
                                }
                                dataFormat(dataCell, value);
                            } else if (j == 10) {
                                Date value = list.get(i).getEndTime();
                                if (value != null) {
                                    dataFormat(dataCell, value);
                                } else {
                                    dataFormat(dataCell, "缺考");
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return workbook;
    }

    /**
     * 单元格值格式化
     *
     * @param dataCell
     * @param obj
     */
    private static void dataFormat(Cell dataCell, Object obj) {
        if (obj == null) {
            dataCell.setCellValue("");
        } else {
            if (obj instanceof String) {
                dataCell.setCellValue((String) obj);
            } else if (obj instanceof Double) {
                dataCell.setCellValue((Double) obj);
            } else if (obj instanceof Float) {
                dataCell.setCellValue((Float) obj);
            } else if (obj instanceof Long) {
                dataCell.setCellValue((Long) obj);
            } else if (obj instanceof Boolean) {
                dataCell.setCellValue((Boolean) obj);
            } else if (obj instanceof Date) {
                Date d = (Date) obj;
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String createDate = sdf.format(d);
                dataCell.setCellValue(createDate);
            }
        }
    }

    /**
     * 交卷
     *
     * @param studentExamId
     * @return
     */
    @PutMapping("/student-exam/{studentExamId}")
    public AjaxResult finish(@PathVariable Integer studentExamId) {
        log.info("Rest request to delete studentExamQuestion by id:{}", studentExamId);
        Student student = userUtils.getCurrentStudent();
        //校验当前学生是否匹配
        StudentExam studentExam = studentExamService.selectById(studentExamId);
        if (studentExam == null) {
            throw new CustomException("查询不到当前考试信息");
        }
        if (!studentExam.getStudentId().equals(student.getId())) {
            throw new CustomException("当前用户和考试信息不匹配");
        }
        ExamResultVo result = studentExamService.finishExam(studentExamId);
        return AjaxResult.success(result);
    }

    /**
     * 批阅试卷详情
     *
     * @return
     */
    @GetMapping("/read-over/{studentExamId}")
    public AjaxResult queryDetails(@PathVariable Integer studentExamId) {
        ExamResultVo result = studentExamService.queryDetails(studentExamId);
        return AjaxResult.success(result);
    }

    /**
     * 批阅试卷
     *
     * @return
     */
    @PutMapping("/read-over")
    public AjaxResult modify(@Valid @RequestBody StudentExam dto) {

        ExamResultVo result = studentExamService.readOver(dto);
        return AjaxResult.success(result);

    }


    /**
     * 统计分析
     *
     * @return
     */
    @GetMapping("/exam-statistcs/{examId}")
    public AjaxResult statistics(@PathVariable Integer examId) {
        ExamStatisticsVo result = studentExamService.statistics(examId);
        return AjaxResult.success(result);
    }


    /**
     * 统计分析 统计图
     * examId 考试id
     * intervalValue 间隔值（10,20,30）
     *
     * @return
     */
    @GetMapping("/statistcs-map/{examId}/{intervalValue}")
    public AjaxResult statisticsMap(@PathVariable Integer examId, @PathVariable Integer intervalValue) {
        List<MapVo> result = studentExamService.statisticsMap(examId, intervalValue);
        return AjaxResult.success(result);
    }


    /**
     * 统计分析 客观题分析
     * examId 考试id
     *
     * @return
     */
    @GetMapping("/objective-problem/{examId}")
    public AjaxResult objectiveProblem(@PathVariable Integer examId) {
        List<StudentExamQuestionVo> questionList = studentExamService.objectiveProblem(examId);
        return AjaxResult.success(questionList);
    }

    /**
     * 交卷后考试成绩界面展示
     *
     * @param studentExamId
     * @return
     */
    @GetMapping("/result/{studentExamId}")
    public AjaxResult examResult(@PathVariable Integer studentExamId) {
        log.info("Rest request to delete studentExamQuestion by id:{}", studentExamId);

        StudentExamPaperVo result = studentExamService.examResult(studentExamId);

        return AjaxResult.success(result);
    }


    /**
     * 导入主观题总成绩
     *
     * @param file
     * @return
     */
    @PostMapping("/read-over/{examId}")
    public AjaxResult insert(@PathVariable Integer examId, MultipartFile file) throws Exception{

        int id = studentExamService.toLead(file, examId);
        if (id == -1) {
            return AjaxResult.error(-1, "导入学员信息为空");
        }
        if (id == -2) {
            return AjaxResult.error(-2, "导入信息不完整，请核对");
        }
        return AjaxResult.success();
    }
}
